package dev.ece.suit.defer;

import dev.ece.core.cells.model.base.FboUI;
import dev.ece.core.cells.model.base.SquareUI;
import dev.ece.core.cells.world.World3D;
import dev.ece.core.sprite.Component;
import dev.ece.core.texture.FBOS;
import dev.ece.util.tools.Camera;
import dev.ece.util.tools.Projection;
import dev.ece.util.tools.Screen;

/**
 * @author 潜行的青衣
 * @see
 */
public class DeferRenderComponent extends Component<Float, SquareUI<Float>> {

	/**
	 * 
	 */
	private static final long serialVersionUID = -4835536988173833190L;

	private DeferRenderShader deferRenderShader;
	
	private Screen screen;
	
	private Camera camera = new Camera();
	
	private Projection projection;
	
	private FBOS defer;
	
	private World3D world;
	
	public DeferRenderComponent(DeferRenderShader deferRenderShader, World3D world) throws Exception {
		this(new FboUI(world.getScreen().getWidth(), world.getScreen().getHeight()), 
				deferRenderShader, world, FBOS.createDeferredFBOS(world.getScreen().getWidth(), world.getScreen().getHeight()));
	}
	
	/**
	 * @param model
	 * @throws Exception 
	 */
	public DeferRenderComponent(SquareUI<Float> model, DeferRenderShader deferRenderShader, World3D world, FBOS defer) throws Exception {
		super(model);
		this.world = world;
		this.deferRenderShader = deferRenderShader;
		this.defer = defer;
		this.screen = new Screen(defer.getWidth(), defer.getHeight());
		this.camera.setPosition(0, 0, 2f);
		this.projection = new Projection().set2DScreen(screen);
		this.initialize();
	}

	public void begin() {
		defer.begin();
	}
	
	public synchronized void render() {
		if(this.isVisible() && this.isInitialized()) {
			this.screen.glViewPort();
			this.projection.glProjection2D();
			this.camera.lookAt();
			this.render(this.camera);
		}
	}
	

	@Override
	public void onRender(Camera camera) {
		this.deferRenderShader.glUseProgram();
		this.deferRenderShader.glModelViewProjectMatrix();
		this.deferRenderShader.glDeferHandler(defer);
		this.deferRenderShader.glDecalHandler(world.getDecal());
		//3D世界相机
		this.deferRenderShader.glCamera(world.getCamera());
		this.deferRenderShader.glShadowInfo(world.getShadowinfo());
		super.onRender(camera);
	}
	
	@Override
	public float getWidth() {
		return this.getUi().getWidth();
	}

	@Override
	public float getHeight() {
		return this.getUi().getHeight();
	}

	public DeferRenderShader getDeferRenderShader() {
		return deferRenderShader;
	}

	public FBOS getDefer() {
		return defer;
	}

	public World3D getWorld() {
		return world;
	}

	@Override
	public void destroy() {
		super.destroy();
		defer.destroy();
		defer = null;
	}

}
